package dontCare.gwtester.client.gwt.leakyAbstraction;

import java.util.ArrayList;
import java.util.List;

import com.google.gwt.core.client.GWT;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.user.client.Random;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;

import dontCare.gwtester.client.tool.SourceUrl;
import dontCare.gwtester.client.tool.UnitWidget;

public class ObjectInit extends UnitWidget{
	private static ObjectInitBinder uiBinder = GWT.create(ObjectInitBinder.class);
	interface ObjectInitBinder extends UiBinder<Widget, ObjectInit> {}
	
	@UiField Label staticValue;
	@UiField Label objectValue;
	@UiField Label sumFun;
	
	public ObjectInit(){
		initWidget(uiBinder.createAndBindUi(this));
		objectValue.setText(""+new Foo().getValue());		
		staticValue.setText(""+Foo.INSTANCE.getValue());
		
		sumFun.setText(""+Cache.getSum()); //FIXME WHY????
	}

	@Override
	public List<String> getSourceUrl() {
		ArrayList<String> result = new ArrayList<String>();
		result.add(SourceUrl.genJava(ObjectInit.class));
		result.add(SourceUrl.genUiXml(ObjectInit.class));
		return result;
	}

	@Override
	public HTML getDescription() {
		return new HTML(
			"第一則出自《Java Puzzler》的謎題 49。<br />" +
			"以 Java 的運作邏輯，INSTANCE 在初始化時 RANDOM 還是預設值（0），" +
			"因此無論 JRE 重啟幾次，Foo.INSTANCE.getValue() 得到的值都會是 0。<br />" +
			"在 Development mode 時會得到 0，但是在 Production Mode 時會得到 NaN。" +
			"這似乎表示 GWT 漏掉要先初始化 RANDOM。<hr/>" +
			"第二則出自《Java Puzzler》的謎題 52。"
		);
	}

	@Override
	public String getName() {
		return "物件初始化問題";
	}
}

class Foo{
	public static final Foo INSTANCE = new Foo();
	private final int value;
	private static final int RANDOM = Random.nextInt(100);
	
	public Foo(){ value = RANDOM; }
	public int getValue(){ return value; }
}

class Cache{
	static{ initializeIfNecessary(); }
	
	private static int sum;
	public static int getSum(){
		initializeIfNecessary();
		return sum;
	}

	private static boolean initialized = false;
	private static void initializeIfNecessary() {
		if(!initialized){
			for(int i=0; i<100; i++){
				sum+=i;
			}
			initialized=true;
		}
	}
}